package org.hs.phd.odi.bgsub.tracking;

import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;

import org.hs.phd.odi.bgsub.features.FeatureMatcher;
import org.hs.phd.odi.bgsub.vob.VisualObject;

public class ObjectListMatcher {

	private List<TrackedObject> nonMatchingTracks;
	private IdentityHashMap<TrackedObject, VisualObject> matchingTracks;
	private List<VisualObject> newObjects;
	private final FeatureMatcher featureMatcher;
	



	public ObjectListMatcher(FeatureMatcher featureMatcher) {
		this.featureMatcher = featureMatcher;
	}

	public void match(List<TrackedObject> trackedObjects, List<VisualObject> currentFrameObjects) {
		nonMatchingTracks = new ArrayList<TrackedObject>();
		matchingTracks = new IdentityHashMap<TrackedObject, VisualObject>();
		newObjects = new ArrayList<VisualObject>();
		
		matchTracksAndObjects(trackedObjects, currentFrameObjects);
	}

	private void matchTracksAndObjects(List<TrackedObject> trackedObjects, 
			List<VisualObject> currentFrameObjects) 
	{
		
		nonMatchingTracks.addAll(trackedObjects);
		
		for(VisualObject obj : currentFrameObjects){
			
			TrackedObject matchingTrack = findTwoWayBestMatch(currentFrameObjects, nonMatchingTracks, obj);
			
			if(matchingTrack != null){
				matchingTracks.put(matchingTrack, obj);
				nonMatchingTracks.remove(matchingTrack);
			}else{
				newObjects.add(obj);
			}
		}
		
		assert nonMatchingTracks.size() + matchingTracks.size() == trackedObjects.size();
		assert newObjects.size() + matchingTracks.size() == currentFrameObjects.size();
		
//		System.out.printf( "# tracks : %d, # obj %d, # match : %d, # xtra tracks: %d,  # xtra obj: %d \n" , 
//				trackedObjects.size(), currentFrameObjects.size(), matchingTracks.size(), nonMatchingTracks.size(), newObjects.size());
		
		
	}

	private TrackedObject findTwoWayBestMatch(List<VisualObject> srcList, List<TrackedObject> destList, VisualObject srcObject) {
		TrackedObject matchingTrack = (TrackedObject) featureMatcher.findBestMatch(srcObject, destList);

		if(matchingTrack != null){
			VisualObject twoWayBestMatch = featureMatcher.findBestMatch(matchingTrack, srcList);
			
			if( srcObject != twoWayBestMatch ){
				matchingTrack = null;
			}
		}
		return matchingTrack;
	}


	public List<TrackedObject> getNonMatchingTracks() {
		return nonMatchingTracks;
	}

	public IdentityHashMap<TrackedObject, VisualObject> getMatchingTracks() {
		return matchingTracks;
	}

	public List<VisualObject> getNewObjects() {
		return newObjects;
	}

}
